import { Inject, Injectable } from "@nestjs/common";
import { InjectRepository } from "@nestjs/typeorm";
import e from "express";
import pinyin from "pinyin";
import { async } from "rxjs";
import { PageQuery } from "src/common/page/PageQuery";
import { Result } from "src/common/Result";
import { StringUtils } from "src/common/utils/StringUtils";
import { GoodsDto } from "src/dto/GoodsDto";
import { Goods } from "src/entity/Goods";
import { GoodsPrice } from "src/entity/GoodsPrice";
import { FindOptionsWhere, Repository } from "typeorm";
import { CollectionUtils } from "src/common/utils/CollectionUtils";
import { Stock } from "src/entity/Stock";

@Injectable()
export class GoodsService {
    
    @InjectRepository(Goods)
    private goodsRepository:Repository<Goods>;

    @InjectRepository(GoodsPrice)
    private goodsPriceRepository: Repository<GoodsPrice>;

    @InjectRepository(Stock)
    private stockRepository: Repository<Stock>;

    /**
     * 添加商品
     * @param dto 
     */
    async addGoods(dto: GoodsDto) {
        // if(dto.originGoodsCode) {
            
        // }
        let pinyinname = pinyin(dto.goodsName, {style: 4});
        let lowniki = pinyinname.join("");
        let upniki = lowniki.toUpperCase();
        dto.niki = upniki + "," + lowniki;
        await this.goodsRepository.insert(dto);            
        if (dto.goodsPriceList) {
            dto.goodsPriceList.forEach(item => {
                item.goodsId = dto.id;
            })
            await this.goodsPriceRepository.save(dto.goodsPriceList);
        }
        return Result.success();
    }


    async selectList(query: PageQuery<GoodsDto>) {    
        let queryBuilder = this.goodsRepository.createQueryBuilder("g")
            .leftJoinAndMapMany("g.GoodsPriceList", "goods_price", "gp", "g.id = gp.goods_id")
            .where("1=1");
        let param = query.param;
        if (param?.goodsCode) {
            queryBuilder.andWhere(`g.goods_code = '${param.goodsCode}'`);
        }
        if (param?.goodsName) {
            queryBuilder.andWhere(`(g.goods_name like '%${param.goodsName}%' 
            or g.niki like '%${param.goodsName}%' or FIND_IN_SET('${param.goodsName}', g.niki))`);
        }
        if (StringUtils.isNotEmpty(param?.status)) {
            queryBuilder.andWhere(`g.status = ${+param.status}`)
        }
        return await PageQuery.getManyAndCount(query, queryBuilder);
    }

    /**
     * 商品详情
     * @param query 
     */
    async goodsQuery(query: GoodsDto): Promise<Goods> {
        let where :FindOptionsWhere<Goods> = {};
        if (query?.goodsCode) {
            where.goodsCode = query.goodsCode;
        }
        if (query?.goodsName) {
            where.goodsName = query.goodsName;
        }
        let data = await this.goodsRepository.findOne({
            where: where, 
            relations: [
                "goodsPriceList", "goodsPriceList.unit", 
                "stockList", "stockList.unit"
            ]
        });
        return data;
    }   


    /**
     * 商品删除
     * @param dto 
     */
    async remove(dto: GoodsDto) {
        let {goodsCodeList} = dto;
        let goodsCode = goodsCodeList[0];
        let one = await this.goodsRepository.findOne({
            where: {
                goodsCode
            },
            relations: [
                "goodsPriceList"
            ]
        });
        
        if (!one) {
            return Result.failed("数据异常!");
        }

        await this.goodsRepository.remove(one);
        return Result.success();
    }

    /**
     * 商品更新
     * @param dto 
     */
    async update(dto: GoodsDto) {
        let {goodsPriceList, goodsCode, stockList} = dto;

        let one = await this.goodsRepository.findOne({
            where: {
                goodsCode
            },
            relations: [
                "goodsPriceList",
                "stockList"
            ]
        });

        // 修改商品价格
        if (CollectionUtils.isNotEmpty(goodsPriceList)) {
            if (CollectionUtils.isNotEmpty(one.goodsPriceList) ) {
                for (const item of one.goodsPriceList) {
                    let price = goodsPriceList.find(o => o.unitId == item.unitId);
                    item.price = price.price;
                }
            } else {
                for (const item of goodsPriceList) {
                    let price = new GoodsPrice();
                    price.goodsId = one.id;
                    price.unitId = item.unitId;
                    price.price = item.price;
                    
                    one.goodsPriceList = [...one.goodsPriceList, price]
                }
            }
            await this.goodsPriceRepository.manager.transaction( async transationManager => {
                await transationManager.withRepository(this.stockRepository).save(one.goodsPriceList);
            });
        }
        // 修改库存
        if (CollectionUtils.isNotEmpty(stockList)) {
            let insert: Stock[] = stockList.filter(o => !o.id);
            this.stockRepository.manager.transaction (async transation => {
                if (CollectionUtils.isNotEmpty(insert)) {
                    insert.forEach(item => {
                        item.goodsId = one.id;
                    })
                    await this.stockRepository.save(insert)
                }
                if (CollectionUtils.isNotEmpty(one.stockList)) {
                    for (const item of one.stockList) {
                        let stock = stockList.find(o => o.unitId == item.unitId);
                        item.count = stock.count;
                    }
                } else {
                    for (const item of stockList) {
                        let stock = new Stock();
                        stock.goodsId = one.id;
                        stock.unitId = item.unitId;
                        stock.count = item.count;
                        
                        one.stockList = [...one.stockList, stock]
                    }
                }
                await this.stockRepository.manager.transaction(async transationManager => {
                    await transationManager.withRepository(this.stockRepository).save(one.stockList);
                });
            })
        }
        return Result.success();
    }
}